package com.flex.core.validate;

import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Map;

import org.springframework.stereotype.Component;

import com.flex.core.validate.annotation.Validation;
import com.flex.core.validate.annotation.Validations;

@Component
public class ValidateManager {

	/**
	 * 对所有属性进行验证
	 * 
	 * @return
	 */
	public Map<String, String> validate(Class<?> clazz) {
		Map<String, String> map = new HashMap<String, String>();
		Field[] fields = clazz.getDeclaredFields();
		for (Field field : fields) {
			String fieldName = field.getName();
			validateField(getValidations(field),
					getMessageKey(clazz, fieldName), invokeMethod(clazz,
							fieldName), map);
		}
		return map;
	}

	/**
	 * 对单个属性进行验证
	 * 
	 * @param fileName
	 * @return
	 */
	public Map<String, String> validate(Class<?> clazz, String fieldName) {
		if (fieldName == null) {
			return validate(clazz);
		}
		Field field = null;
		try {
			field = clazz.getDeclaredField(fieldName);
		} catch (Exception e) {
			e.printStackTrace();
		}
		Map<String, String> map = new HashMap<String, String>();
		validateField(getValidations(field), getMessageKey(clazz, fieldName),
				invokeMethod(clazz, fieldName), map);
		return map;
	}

	/**
	 * 具体进行验证的方法,验证后将错误信息记入到map中
	 * 
	 * @param vs
	 *            验证器
	 * @param key
	 *            错误信息的键
	 * @param fieldValue
	 *            属性的值
	 * @param map
	 *            装载错误信息的map
	 */
	private void validateField(Validation[] vs, String key, Object fieldValue,
			Map<String, String> map) {
		for (Validation validateAnnotation : vs) {
			if (validateAnnotation != null) {
				String msg = ValidateContext.validate(validateAnnotation,
						fieldValue);
				if (!msg.equals("")) {
					map.put(key, msg);
					break;
				}
			}
		}
	}

	/**
	 * 获得该field上的所有验证器的数组
	 * 
	 * @param field
	 * @return
	 */
	private Validation[] getValidations(Field field) {
		Validation[] validations = new Validation[1];
		if (field != null) {
			if (field.isAnnotationPresent(Validation.class)) {
				validations[0] = field.getAnnotation(Validation.class);
				return validations;
			}
			if (field.isAnnotationPresent(Validations.class)) {
				return field.getAnnotation(Validations.class).value();
			}
		}
		return validations;
	}

	/**
	 * 通过反射获得对象的名称和传入的属性名称拼装成存储错误消息的key字符串
	 * 
	 * @return
	 */
	private String getMessageKey(Class<?> clazz, String fieldName) {
		String objectName = clazz.getName();
		int index = objectName.lastIndexOf(".");
		if (index > 0) {
			objectName = objectName.substring(index + 1);
		}
		StringBuffer sb = new StringBuffer();
		sb.append(objectName);
		sb.append("_");
		sb.append(fieldName);
		sb.append("_msg");
		return sb.toString();
	}

	/**
	 * 通过反射调用该属性的get方法获得属性的值
	 * 
	 * @param filedName
	 * @return
	 */
	private Object invokeMethod(Class<?> clazz, String filedName) {
		filedName = filedName.substring(0, 1).toUpperCase()
				+ filedName.substring(1);
		try {
			Method method = clazz.getMethod("get" + filedName);
			return method.invoke(this);
		} catch (Exception e) {
			return null;
		}
	}

}
